package com.dp.server;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.dp.client.dto.VueloDTO;
import com.dp.client.servicios.vuelo.IServiciosVuelo;
import com.dp.server.entities.Paquete;
import com.dp.server.entities.PlanDeVuelo;
import com.dp.server.entities.ReservaVuelo;
import com.dp.server.entities.Vuelo;
import com.dp.shared.FieldVerifier;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

public class IServiciosVueloImpl extends RemoteServiceServlet implements IServiciosVuelo{
	// TODO : falta provar todo menos el query D: , metanle fe nomas si se cae me avisan xD
	MantenimientoGenerico<Vuelo> mVuelo = new MantenimientoGenerico<>("Vuelo");
	MantenimientoGenerico<Paquete> mPaquete = new MantenimientoGenerico<>("Paquete");
	MantenimientoGenerico<PlanDeVuelo> mPlan = new MantenimientoGenerico<>("PlanDeVuelo");
	static int cte = 60 * 60 * 1000;
	static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	static long oo = 1 << 60;
	@Override
	public Boolean cancelarVuelo(VueloDTO vuelo) {
		Vuelo v = mVuelo.buscarID( vuelo.id );
		v.cancelar();
		mVuelo.modifica( v );
		List<ReservaVuelo> reservas = getReservas( vuelo.id );
		List<Paquete> pqts = new ArrayList<Paquete>();
		for( ReservaVuelo r : reservas ){
			pqts.add( mPaquete.buscarID(r.getIdPaquete() ) );
		}
		return notificarPaquetesReruteo( pqts );
	}

	private List<ReservaVuelo > getReservas( int id ){
		return (List<ReservaVuelo>) MantenimientoGenerico
		.query("from ReservaVuelo where idVuelo = " + id + " and eliminado = 0" );
	}
	@Override
	public Boolean avanzarEstado(VueloDTO vuelo) {
		Vuelo v = mVuelo.buscarID( vuelo.id );
		int idEstado = v.getIdEstado();
		if( idEstado > 1 ) return true;
		if( idEstado == 0 ) return despegar( v , new Date() );
		else 				return aterrizar( v , new Date() );
	}
	
	public boolean despegar( Vuelo vuelo , Date fecha  ){
		vuelo.despegar();
		vuelo.setFechaHoraRealSalida( fecha );
		mVuelo.modifica( vuelo );
		List<ReservaVuelo> reservas = getReservas(vuelo.getId() );
		List<Paquete> pqts = new ArrayList<Paquete>();
		for( ReservaVuelo r : reservas ){
			pqts.add( mPaquete.buscarID(r.getIdPaquete() ) );
		}
		List<Paquete> reruteo = new ArrayList<Paquete>();
		for( Paquete p : pqts ){
			if( p.getAlmacenActual() != vuelo.getIdOrigen() ) continue;
			if( p.getEstadoPaquete() != 3 ){
				reruteo.add( p );
				continue;
			}
			p.subirPaquete();
			p.setVueloActual( vuelo.getId() );
			PlanDeVuelo pdv = mPlan.buscarID( p.getPlanDeVuelo() );
			pdv.avanzar();
			mPlan.modifica( pdv );
			mPaquete.modifica( p );
		}
		notificarPaquetesReruteo( reruteo );
		return true; //notificarPaquetesReruteo(vuelo);
	}
	
	public boolean aterrizar( Vuelo vuelo , Date fecha ){
		vuelo.aterrizar();
		vuelo.setFechaHoraRealLlegada( fecha );
		mVuelo.modifica( vuelo );
		List<ReservaVuelo> reservas = getReservas(vuelo.getId() );
		List<Paquete> pqts = new ArrayList<Paquete>();
		for( ReservaVuelo r : reservas ){
			pqts.add( mPaquete.buscarID(r.getIdPaquete() ) );
		}
		for( Paquete p : pqts ){
			p.bajarPaquete();
			p.setAlmacenActual( vuelo.getIdDestino() );
			PlanDeVuelo pdv = mPlan.buscarID( p.getPlanDeVuelo() );
			pdv.avanzar();
			mPlan.modifica( pdv );
			mPaquete.modifica( p );
		}
		return true;	
	}
	
	private boolean notificarPaquetesReruteo( List<Paquete> list ){
		List<PlanDeVuelo> list_plan = new ArrayList<PlanDeVuelo>();
		for( int i = 0 ; i < list.size() ; i++ ){
			PlanDeVuelo plan = mPlan.buscarID( list.get( i ).getPlanDeVuelo() );
			plan.liberarRutaRestante();
			plan.setEliminado( true );
			list_plan.add( plan );
			list.get(i).reruteo();
		}
		mPaquete.registrarBatch( list , 50 );
		mPlan.registrarBatch(list_plan, 50);
		return true;
	}

	
	@Override
	public List<VueloDTO> getQuery( String id , String idOrigen, String idDestino,
			Date inicio, Date fin, String idEstado) {
		String sInicio = "0000-00-00 00:00:00" , sFin = "9999-12-12 00:00:00";
		if( inicio != null ) inicio.setTime(( inicio.getTime() / cte ) * cte );
		if( fin != null )    fin.setTime(( fin.getTime() / cte ) * cte );
		if( inicio != null ) sInicio = format.format( inicio );
		if( fin != null ) sFin = format.format( fin );
		
		String fecha = "fechaHoraSalida between '" + sInicio + "' and '" + sFin  + "' " ;
		String qOrigen = " 1 = 1 ";
		String qDestino = " 1 = 1 ";
		String qEstado = " 1 = 1 ";
		String qId = " 1 = 1 ";
		if( FieldVerifier.isId(id) ) qId = "id = " + id;
		if( FieldVerifier.isId( idOrigen ) ) qOrigen = "idOrigen = " + idOrigen;
		if( FieldVerifier.isId( idDestino ) ) qDestino = "idDestino = " + idDestino;
		if( toInt( idEstado ) >= 0 ) qEstado = "idEstado = " + idEstado;
		List<VueloDTO> ans = new ArrayList<VueloDTO>();
		String query = "from Vuelo where " + fecha  + " and " + qOrigen + " and " + qDestino + " and " + qEstado +
					 " and " + qId + " and eliminado = 0" ;
		System.out.println( query );
		List<Vuelo> listaVuelo = (List<Vuelo>) MantenimientoGenerico.query( query );
		for( Vuelo v : listaVuelo ) ans.add(v.extractDTO());
		return ans;
	}
	
	int toInt( String s ){
		try {
		 int ans =  Integer.parseInt( s );
		 return ans;
		} catch( Exception e ){
			return -1;
		}
	}

	/*
	 * Se tiene que devolver la cantidad de paquetes que subieron al vuelo con idVuelo y 
	 * la cantidad total de paquetes;
	 * Ans[ 0 ] = subieron;
	 * Ans[ 1 ] = total;
	 */
	@Override
	public List<Integer> getPaquetesAsignados(int idVuelo) {
		List< Integer > ans = new ArrayList<Integer>();
		List<ReservaVuelo> reservas = getReservas( idVuelo );
		List<Paquete> pqts = new ArrayList<Paquete>();
		Vuelo v = mVuelo.buscarID( idVuelo );
		int total = reservas.size();
		int fuera = 0;
		for( ReservaVuelo r : reservas ){
			pqts.add( mPaquete.buscarID(r.getIdPaquete() ) );
		}
		for( Paquete p : pqts ){
			if( p.getAlmacenActual() != v.getIdOrigen() ) fuera++;
			else if( p.getEstadoPaquete() != 3 ) fuera++;
		}
		ans.add( fuera ); ans.add( total );
		return ans;
	}
}
